package gps.monitor.jt809server.util;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

/**
 * @author cyq
 * @date 2021/11/6
 * @desc talk is cheep,show me the code
 */
public final class ProtocolUtils {

    /**
     * 此方法没有实现0拷贝
     * 去除转义：
     * a) 若数据内容中有出现字符 0x5b 的，需替换为字符 0x5a 紧跟字符 0x01;
     * b) 若数据内容中有出现字符 0x5a 的，需替换为字符 0x5a 紧跟字符 0x02;
     * c) 若数据内容中有出现字符 0x5d 的，需替换为字符 0x5e 紧跟字符 0x01;
     * d) 若数据内容中有出现字符 0x5e 的，需替换为字符 0x5e 紧跟字符 0x02.
     * @param byteBuf
     */
    public static ByteBuf deEscape(final ByteBuf byteBuf) {
        int len = byteBuf.writerIndex() - byteBuf.readerIndex();
        int counter = 0;
        ByteBuf newBuf = null;
        while (counter < len) {
            int one = byteBuf.getByte(counter);
            if (one == 90) {
                int two = byteBuf.getByte(counter+1);
                if (two == 1) {
                    ++counter;
                    if (newBuf == null) {
                        newBuf = Unpooled.buffer(len);
                        newBuf.writeBytes(byteBuf,byteBuf.readerIndex(),counter - 1);
                    }
                    newBuf.writeByte(0x5b);
                }else if (two == 2) {
                    ++counter;
                    if (newBuf == null) {
                        newBuf = Unpooled.buffer(len);
                        newBuf.writeBytes(byteBuf,byteBuf.readerIndex(),counter-1);
                    }
                    newBuf.writeByte(0x5a);
                }else if (newBuf != null) {
                    newBuf.writeByte(one);
                }
            }else if (one == 94) {
                int two = byteBuf.getByte(counter+1);
                if (two == 1) {
                    ++counter;
                    if (newBuf == null) {
                        newBuf = Unpooled.buffer(len);
                        newBuf.writeBytes(byteBuf,byteBuf.readerIndex(),counter-1);
                    }
                    newBuf.writeByte(0x5d);
                }else if (two == 2) {
                    ++counter;
                    if (newBuf == null) {
                        newBuf = Unpooled.buffer(len);
                        newBuf.writeBytes(byteBuf,byteBuf.readerIndex(),counter-1);
                    }
                    newBuf.writeByte(0x5e);
                }else if (newBuf != null) {
                    newBuf.writeByte(one);
                }
            }else if (newBuf != null) {
                newBuf.writeByte(one);
            }
            ++counter;
        }

        return newBuf == null ? byteBuf : newBuf;
    }

    /**
     *
     * @param byteBuf
     * @param m
     * @param a
     * @param c
     * @param key
     */
    public static void encryptBody(final ByteBuf byteBuf, int m, int a, int c, long key) {
        int start = byteBuf.readerIndex();
        int end = byteBuf.writerIndex() - 1;
        if (start < end) {
            key = a * (key % m) + c;
            byte one = byteBuf.getByte(start);
            byte t = (byte) ((key >> 20) & 0xFF);
            byteBuf.setByte(start, one ^ t);
            ++start;
        }
    }

}
